/**
 ******************************************************************************
 * @file    lpi2c.c
 * @author  hyseim software Team
 * @date    18-Aug-2023
 * @brief   This file provides all the tmp functions.
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2020 Hyseim. Co., Ltd.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "lpi2c.h"
#include "common.h"


/** @addtogroup IM110GW_Driver
 * @{
 */

/** @defgroup LPI2C
 * @brief LPI2C driver modules
 * @{
 */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup LPI2C_Private_Functions
  * @{
  */

/**
 * @brief  Deinitializes the LPI2C peripheral registers to their default reset values.
 * @return None
 */
void LPI2C_DeInit(void)
{
    im_write32(CRU_AO_BASE + 0x8, (0x1 << 12) | ((0x1 << 12) << 16));
    im_write32(CRU_AO_BASE + 0x8, (0x0 << 12) | ((0x1 << 12) << 16));
}

/**
 * @brief  Initializes the LPI2C peripheral according to the specified 
 *         parameters in the LPI2C_InitStruct.
 * @param  LPI2C_CON: specifies the configuration for the specified 
 *         LPI2C peripheral.
 * @return None
 */
void LPI2C_Init(uint32_t LPI2C_CON)
{
    LPI2C->CON = LPI2C_CON;
}

/**
 * @brief  Configures the specified LPI2C target address.
 * @param  TargetAddress: specifies the LPI2C target address.
 * @return None
 */
void LPI2C_TargetAddressConfig(uint32_t TargetAddress)
{
    LPI2C->TAR = TargetAddress;
}

/**
 * @brief  Configures the specified LPI2C own address.
 * @param  Address: specifies the LPI2C own address.
 * @return None
 */
void LPI2C_OwnAddressConfig(uint16_t Address)
{
    LPI2C->SAR = Address;
}

/**
 * @brief  Configures the LPI2C HS mode master code.
 * @param  Code: specifies the LPI2C HS mode master code.
 * @return None
 */
void LPI2C_HighSpeedModeMasterCodeConfig(uint8_t Code)
{
    LPI2C->HS_MADDR = Code;
}

/**
 * @brief  Returns the transmit abort source for the specified LPI2C.
 * @return The transmit abort source.
 */
uint32_t LPI2C_GetTxAbortSource(void)
{
    return LPI2C->TX_ABRT_SOURCE;
}

/**
 * @brief  Configures the specified LPI2C SCL stuck at low timeout.
 * @param  Timeout: specifies the SCL stuck at low timeout.
 * @return None
 */
void LPI2C_SCLStuckAtLowTimeoutConfig(uint32_t Timeout)
{
    LPI2C->SCL_STUCK_AT_LOW_TIMEOUT = Timeout;
}

/**
 * @brief  Configures the specified LPI2C SDA stuck at low timeout.
 * @param  Timeout: specifies the SDA stuck at low timeout.
 * @return None
 */
void LPI2C_SDAStuckAtLowTimeoutConfig(uint32_t Timeout)
{
    LPI2C->SDA_STUCK_AT_LOW_TIMEOUT = Timeout;
}

/**
 * @brief  Enables or disables the specified LPI2C peripheral.
 * @param  NewState: new state of the LPI2C peripheral.
 *         This parameter can be: ENABLE or DISABLE.
 * @return None
 */
void LPI2C_Cmd(FunctionalState_t NewState)
{
    if (NewState != DISABLE) {
        LPI2C->ENABLE |= LPI2C_ENABLE_ENABLE;
    }
    else {
        LPI2C->ENABLE &= ~LPI2C_ENABLE_ENABLE;
    }
}

/**
 * @brief  Choose direction when as a Master.
 * @param  NewDirection: new direction of I2c Master.
 *         This parameter can be: WRITE or READ.
 * @return None
 */
void LPI2C_MasterDirectionConfig(I2C_MasterDirection_t NewDirection)
{
    if (NewDirection != WRITE) {
        LPI2C->CON |= LPI2C_CON_MASTER_READ;
    }
    else {
        LPI2C->CON &= ~LPI2C_CON_MASTER_READ;
    }
}

/**
 * @brief  Enables or disables generate NACK after data byte received
 *         when as slave-receiver.
 * @param  NewState: new state of generate NACK after data byte received.
 *         This parameter can be: ENABLE or DISABLE.
 * @return None
 */
void LPI2C_SlaveDataNAckOnlyConfig(FunctionalState_t NewState)
{
    if (NewState != DISABLE) {
        LPI2C->SLV_DATA_NACK_ONLY = 0x01;
    }
    else {
        LPI2C->SLV_DATA_NACK_ONLY = 0x00;
    }
}

/**
 * @brief  Enables or disables the General Call ACK Generate.
 * @param  NewState: new state of the General Call ACK Generate.
 *         This parameter can be: ENABLE or DISABLE.
 * @return None
 */
void LPI2C_AckGeneralCallCmd(FunctionalState_t NewState)
{
    if (NewState != DISABLE) {
        LPI2C->ACK_GENERAL_CALL = 0x01;
    }
    else {
        LPI2C->ACK_GENERAL_CALL = 0x00;
    }
}

/**
 * @brief  Read data from Rx FIFO.
 * @return The received data.
 */
uint16_t LPI2C_ReadData(void)
{
    return LPI2C->DATA_CMD;
}

/**
 * @brief  Write data and command Tx FIFO.
 * @param  LPI2C_DataCmd: the data and command to write.
 * @return None
 */
void LPI2C_WriteDataCmd(uint16_t LPI2C_DataCmd)
{
    LPI2C->DATA_CMD = LPI2C_DataCmd;
}

/**
 * @brief  Checks whether the specified LPI2C flag is set or not.
 * @param  LPI2C_FLAG: specifies the flag to check. 
 *         This parameter can be one of the following values:
 *         @arg @ref LPI2C_FLAG_ACTIVITY
 *         @arg @ref LPI2C_FLAG_TFNF
 *         @arg @ref LPI2C_FLAG_TFE
 *         @arg @ref LPI2C_FLAG_RFNE
 *         @arg @ref LPI2C_FLAG_RFF
 *         @arg @ref LPI2C_FLAG_MST_ACTIVITY
 *         @arg @ref LPI2C_FLAG_SLV_ACTIVITY
 *         @arg @ref LPI2C_FLAG_MST_HOLD_TX_FIFO_EMPTY
 *         @arg @ref LPI2C_FLAG_MST_HOLD_RX_FIFO_FULL
 *         @arg @ref LPI2C_FLAG_SLV_HOLD_TX_FIFO_EMPTY
 *         @arg @ref LPI2C_FLAG_SLV_HOLD_RX_FIFO_FULL
 *         @arg @ref LPI2C_FLAG_SDA_STUCK_NOT_RECOVERED
 *         @arg @ref LPI2C_FLAG_SMBUS_QUICK_CMD_BIT
 *         @arg @ref LPI2C_FLAG_SMBUS_SLAVE_ADDR_VALID
 *         @arg @ref LPI2C_FLAG_SMBUS_SLAVE_ADDR_RESOLVED
 *         @arg @ref LPI2C_FLAG_SMBUS_SUSPEND_STATUS
 *         @arg @ref LPI2C_FLAG_SMBUS_ALERT_STATUS
 * @return The new state of LPI2C_FLAG (SET or RESET).
 */
FlagStatus_t LPI2C_GetFlagStatus(uint32_t LPI2C_FLAG)
{
    FlagStatus_t bitstatus = RESET;

    /* Check the status of the specified LPI2C flag */
    if ((LPI2C->STATUS & LPI2C_FLAG) != (uint32_t)RESET)
    {
        /* LPI2C_FLAG is set */
        bitstatus = SET;
    }
    else
    {
        /* LPI2C_FLAG is reset */
        bitstatus = RESET;
    }
    /* Return the LPI2C_FLAG status */
    return  bitstatus;
}

/**
 * @brief  Enables or disables the specified LPI2C interrupts.
 * @param  LPI2C_IT: specifies the LPI2C interrupt source to be enabled or disabled. 
 *         This parameter can be a combination of the following values:
 *         @arg @ref LPI2C_IT_RX_UNDER
 *         @arg @ref LPI2C_IT_RX_OVER
 *         @arg @ref LPI2C_IT_RX_FULL
 *         @arg @ref LPI2C_IT_TX_OVER
 *         @arg @ref LPI2C_IT_TX_EMPTY
 *         @arg @ref LPI2C_IT_RD_REQ
 *         @arg @ref LPI2C_IT_TX_ABRT
 *         @arg @ref LPI2C_IT_RX_DONE
 *         @arg @ref LPI2C_IT_ACTIVITY
 *         @arg @ref LPI2C_IT_STOP_DET
 *         @arg @ref LPI2C_IT_START_DET
 *         @arg @ref LPI2C_IT_GEN_CALL
 *         @arg @ref LPI2C_IT_RESTART_DET
 *         @arg @ref LPI2C_IT_SCL_STUCK_AT_LOW
 * @param  NewState: new state of the specified LPI2C interrupt.
 *         This parameter can be: ENABLE or DISABLE.
 * @return None.
 */
void LPI2C_ITConfig(uint16_t LPI2C_IT, FunctionalState_t NewState)
{
    if (NewState != DISABLE)
    {
        /* Enable the selected LPI2C interrupt */
        LPI2C->INTR_MASK |= LPI2C_IT;
    }
    else
    {
        /* Disable the selected LPI2C interrupt */
        LPI2C->INTR_MASK &= ~LPI2C_IT;
    }
}

/**
 * @brief  Checks whether the specified LPI2C raw interrupt status.
 * @param  LPI2C_IT: specifies the LPI2C interrupt source to check.
 *         This parameter can be one of the following values:
 *         @arg @ref LPI2C_IT_RX_UNDER
 *         @arg @ref LPI2C_IT_RX_OVER
 *         @arg @ref LPI2C_IT_RX_FULL
 *         @arg @ref LPI2C_IT_TX_OVER
 *         @arg @ref LPI2C_IT_TX_EMPTY
 *         @arg @ref LPI2C_IT_RD_REQ
 *         @arg @ref LPI2C_IT_TX_ABRT
 *         @arg @ref LPI2C_IT_RX_DONE
 *         @arg @ref LPI2C_IT_ACTIVITY
 *         @arg @ref LPI2C_IT_STOP_DET
 *         @arg @ref LPI2C_IT_START_DET
 *         @arg @ref LPI2C_IT_GEN_CALL
 *         @arg @ref LPI2C_IT_RESTART_DET
 *         @arg @ref LPI2C_IT_SCL_STUCK_AT_LOW
 * @return The new state of raw LPI2C_IT (SET or RESET).
 */
ITStatus_t LPI2C_GetRawITStatus(uint16_t LPI2C_IT)
{
    ITStatus_t bitstatus = RESET;

    /* Check the raw status of the specified LPI2C interrupt */
    if (LPI2C->RAW_INTR_STAT & LPI2C_IT)
    {
        /* LPI2C_IT is set */
        bitstatus = SET;
    }
    else
    {
        /* LPI2C_IT is reset */
        bitstatus = RESET;
    }
    /* Return the LPI2C_IT raw status */
    return bitstatus;
}

/**
 * @brief  Checks whether the specified LPI2C interrupt has occurred or not.
 * @param  LPI2C_IT: specifies the LPI2C interrupt source to check.
 *         This parameter can be one of the following values:
 *         @arg @ref LPI2C_IT_RX_UNDER
 *         @arg @ref LPI2C_IT_RX_OVER
 *         @arg @ref LPI2C_IT_RX_FULL
 *         @arg @ref LPI2C_IT_TX_OVER
 *         @arg @ref LPI2C_IT_TX_EMPTY
 *         @arg @ref LPI2C_IT_RD_REQ
 *         @arg @ref LPI2C_IT_TX_ABRT
 *         @arg @ref LPI2C_IT_RX_DONE
 *         @arg @ref LPI2C_IT_ACTIVITY
 *         @arg @ref LPI2C_IT_STOP_DET
 *         @arg @ref LPI2C_IT_START_DET
 *         @arg @ref LPI2C_IT_GEN_CALL
 *         @arg @ref LPI2C_IT_RESTART_DET
 *         @arg @ref LPI2C_IT_SCL_STUCK_AT_LOW
 * @return The new state of LPI2C_IT (SET or RESET).
 */
ITStatus_t LPI2C_GetITStatus(uint16_t LPI2C_IT)
{
    ITStatus_t bitstatus = RESET;

    /* Check the status of the specified LPI2C interrupt */
    if (LPI2C->INTR_STAT & LPI2C_IT)
    {
        /* LPI2C_IT is set */
        bitstatus = SET;
    }
    else
    {
        /* LPI2C_IT is reset */
        bitstatus = RESET;
    }
    /* Return the LPI2C_IT status */
    return bitstatus;
}

/**
 * @brief  Clears the LPI2C's interrupt pending bits.
 * @param  LPI2C_IT: specifies the interrupt pending bit to clear.
 *         This parameter can be a combination of the following values:
 *         @arg @ref LPI2C_IT_RX_UNDER
 *         @arg @ref LPI2C_IT_RX_OVER
 *         @arg @ref LPI2C_IT_TX_OVER
 *         @arg @ref LPI2C_IT_RD_REQ
 *         @arg @ref LPI2C_IT_TX_ABRT
 *         @arg @ref LPI2C_IT_RX_DONE
 *         @arg @ref LPI2C_IT_ACTIVITY
 *         @arg @ref LPI2C_IT_STOP_DET
 *         @arg @ref LPI2C_IT_START_DET
 *         @arg @ref LPI2C_IT_GEN_CALL
 *         @arg @ref LPI2C_IT_RESTART_DET
 *         @arg @ref LPI2C_IT_SCL_STUCK_AT_LOW
 * @return None.
 */
void LPI2C_ClearITPendingBit(uint16_t LPI2C_IT)
{
    if ((LPI2C_IT & (LPI2C_IT_RX_UNDER | LPI2C_IT_RX_OVER | LPI2C_IT_TX_OVER |
                LPI2C_IT_RD_REQ | LPI2C_IT_TX_ABRT | LPI2C_IT_RX_DONE |
                LPI2C_IT_ACTIVITY | LPI2C_IT_STOP_DET | LPI2C_IT_START_DET |
                LPI2C_IT_GEN_CALL | LPI2C_IT_RESTART_DET | LPI2C_IT_SCL_STUCK_AT_LOW)) ==
            (LPI2C_IT_RX_UNDER | LPI2C_IT_RX_OVER | LPI2C_IT_TX_OVER |
            LPI2C_IT_RD_REQ | LPI2C_IT_TX_ABRT | LPI2C_IT_RX_DONE |
            LPI2C_IT_ACTIVITY | LPI2C_IT_STOP_DET | LPI2C_IT_START_DET |
            LPI2C_IT_GEN_CALL | LPI2C_IT_RESTART_DET | LPI2C_IT_SCL_STUCK_AT_LOW))
    {
        (void)LPI2C->CLR_INTR;
    }
    else
    {
        if (LPI2C_IT & LPI2C_IT_RX_UNDER)          (void)LPI2C->CLR_RX_UNDER;
        if (LPI2C_IT & LPI2C_IT_RX_OVER)           (void)LPI2C->CLR_RX_OVER;
        if (LPI2C_IT & LPI2C_IT_TX_OVER)           (void)LPI2C->CLR_TX_OVER;
        if (LPI2C_IT & LPI2C_IT_RD_REQ)            (void)LPI2C->CLR_RD_REQ;
        if (LPI2C_IT & LPI2C_IT_TX_ABRT)           (void)LPI2C->CLR_TX_ABRT;
        if (LPI2C_IT & LPI2C_IT_RX_DONE)           (void)LPI2C->CLR_RX_DONE;
        if (LPI2C_IT & LPI2C_IT_ACTIVITY)          (void)LPI2C->CLR_ACTIVITY;
        if (LPI2C_IT & LPI2C_IT_STOP_DET)          (void)LPI2C->CLR_STOP_DET;
        if (LPI2C_IT & LPI2C_IT_START_DET)         (void)LPI2C->CLR_START_DET;
        if (LPI2C_IT & LPI2C_IT_GEN_CALL)          (void)LPI2C->CLR_GEN_CALL;
        if (LPI2C_IT & LPI2C_IT_RESTART_DET)       (void)LPI2C->CLR_RESTART_DET;
        if (LPI2C_IT & LPI2C_IT_SCL_STUCK_AT_LOW)  (void)LPI2C->CLR_SCL_STUCK_DET;
    }
}

/**
 * @brief  Configures the Receive FIFO threshold.
 * @param  Threshold: The Receive FIFO threshold to set.
 * @param  The RX_FULL interrupt will trigger when the level > Threshold.
 * @return None.
 */
void LPI2C_RxFIFOThresholdConfig(uint8_t Threshold)
{
    LPI2C->RX_TL = Threshold;
}

/**
 * @brief  Configures the Transmit FIFO threshold.
 * @param  Threshold: The Transmit FIFO threshold to set.
 * @note   The TX_EMPTY interrupt will trigger when the level <= Threshold.
 * @return None.
 */
void LPI2C_TxFIFOThresholdConfig(uint8_t Threshold)
{
    LPI2C->TX_TL = Threshold;
}

/**
 * @brief  Returns the number of valid data entries in the receive FIFO buffer.
 * @return The number of valid data entries in the receive FIFO.
 */
uint8_t LPI2C_GetRxFIFOLevel(void)
{
    return LPI2C->RXFLR;
}

/**
 * @brief  Returns the number of valid data entries in the transmit FIFO buffer.
 * @return The number of valid data entries in the transmit FIFO.
 */
uint8_t LPI2C_GetTxFIFOLevel(void)
{
    return LPI2C->TXFLR;
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */
